package org.c797797ty.railway.util;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
/**
 * @author C797797ty
 * @data 2025/11/4 14:27
 */

/**
 * 高并发数据库工具类 - 支持多线程并发访问
 */
public class ConcurrentDBUtil {
    private static HikariDataSource dataSource;

    static {
        try {
            // 加载配置文件
            Properties props = new Properties();
            try (InputStream input = ConcurrentDBUtil.class.getClassLoader().getResourceAsStream("db-dev.properties")) {
                if (input == null) {
                    System.out.println("无法找到db-dev.properties文件，使用默认配置");
                    // 使用默认配置
                    props.setProperty("db.url", "jdbc:mysql://localhost:3307/railway?useSSL=false&serverTimezone=UTC");
                    props.setProperty("db.username", "root");
                    props.setProperty("db.password", "123456");
                } else {
                    props.load(input);
//                    System.out.println("成功加载配置文件");
                }
            }

            Class.forName("com.mysql.cj.jdbc.Driver");
            HikariConfig config = new HikariConfig();
            String dbUrl = props.getProperty("db.url");
            String dbUsername = props.getProperty("db.username");
            String dbPassword = props.getProperty("db.password");

//            System.out.println("数据库URL: " + dbUrl);
//            System.out.println("数据库用户名: " + dbUsername);

            config.setJdbcUrl(dbUrl);
            config.setUsername(dbUsername);
            config.setPassword(dbPassword);
            config.setMaximumPoolSize(100); // 连接池大小
            config.setMinimumIdle(10);
            config.setConnectionTimeout(30000);
            config.setIdleTimeout(600000);
            dataSource = new HikariDataSource(config);

//            System.out.println("数据库连接池初始化成功");
        } catch (Exception e) {
            System.err.println("数据库连接池初始化失败: " + e.getMessage());
            e.printStackTrace();
            throw new RuntimeException("数据库连接池初始化失败", e);
        }
    }

    // 获取数据库连接
    public static Connection getConnection() throws SQLException {
//        System.out.println("获取数据库连接...");
        Connection conn = dataSource.getConnection();
//        System.out.println("成功获取数据库连接");
        return conn;
    }

    // 线程安全的查询方法 - 使用回调函数处理ResultSet
    public static <T> T executeQuery(QueryOperation<T> operation, String sql, Object... params) throws SQLException {
//        System.out.println("执行SQL查询: " + sql);
//        System.out.println("参数: " + java.util.Arrays.toString(params));

        try (Connection conn = getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            setParams(stmt, params);
            try (ResultSet rs = stmt.executeQuery()) {
                T result = operation.process(rs);
//                System.out.println("查询执行完成");
                return result;
            }
        } catch (SQLException e) {
            System.err.println("SQL查询执行失败: " + e.getMessage());
            throw e;
        }
    }

    // 线程安全的查询方法 - 已废弃，请使用带回调函数的版本
    @Deprecated
    public static ResultSet executeQuery(String sql, Object... params) throws SQLException {
        try (Connection conn = getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            setParams(stmt, params);
            return stmt.executeQuery();
        }
    }

    // 线程安全的更新方法
    public static int executeUpdate(String sql, Object... params) throws SQLException {
        try (Connection conn = getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            setParams(stmt, params);
            return stmt.executeUpdate();
        }
    }

    // 线程安全的事务方法
    public static void executeInTransaction(SQLOperation operation) throws SQLException {
        Connection conn = null;
        try {
            conn = getConnection();
            conn.setAutoCommit(false);
            operation.execute(conn);
            conn.commit();
        } catch (SQLException e) {
            if (conn != null) conn.rollback();
            throw e;
        } finally {
            if (conn != null) conn.close();
        }
    }

    // 设置参数
    private static void setParams(PreparedStatement stmt, Object... params) throws SQLException {
        for (int i = 0; i < params.length; i++) {
            stmt.setObject(i + 1, params[i]);
        }
    }

    // SQL操作接口
    @FunctionalInterface
    public interface SQLOperation {
        void execute(Connection conn) throws SQLException;
    }

    // 查询操作接口
    @FunctionalInterface
    public interface QueryOperation<T> {
        T process(ResultSet rs) throws SQLException;
    }
}